//
//  SAdd.swift
//  niuguwang
//
//  Created by BrightLi on 2021/9/4.
//  Copyright © 2021年 taojinzhe. All rights reserved.
//

import Foundation
import UIKit
import SnapKit

extension NSObject
{
    // MARK:返回className
    var className:String{
        get{
            let name =  type(of: self).description()
            if(name.contains(".")){
                return name.components(separatedBy: ".")[1];
            }else{
                return name;
            }            
        }
    }
}

extension DispatchQueue
{
    private static var mainToken: DispatchSpecificKey<()> = {
        let key = DispatchSpecificKey<()>()
        DispatchQueue.main.setSpecific(key: key, value: ())
        return key
    }()
    
    static var isMainThread:Bool{
        return DispatchQueue.getSpecific(key: mainToken) != nil
    }
    
    public class func safeMainAsync(_ block: @escaping ()->()) {
        if DispatchQueue.isMainThread{
            block()
        }else{
            DispatchQueue.main.async {
                block()
            }
        }
    }
}

extension UIView
{
    private struct RuntimeKey
    {
        static var clickBlockKey = "UIView_block"
        static var waitTaskKey = "wait_task"
    }
    
    public var waitTask:STask?
    {
        get{
            return objc_getAssociatedObject(self,&RuntimeKey.waitTaskKey) as? STask
        }
        set{
            objc_setAssociatedObject(self,&RuntimeKey.waitTaskKey,newValue,
                                     .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    @objc public func s_clickBlock(_ block:@escaping ((_ tap:UITapGestureRecognizer) -> ()))
    {
        objc_setAssociatedObject(self,
                                 &RuntimeKey.clickBlockKey,
                                 block,
                                 .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        isUserInteractionEnabled=true
        let tap = UITapGestureRecognizer(target: self, action: #selector(tap(_ :)))
        self.addGestureRecognizer(tap)
    }
    
    @objc public func tap(_ tap:UITapGestureRecognizer)
    {
        if let block = objc_getAssociatedObject(self,&RuntimeKey.clickBlockKey) as? ((UITapGestureRecognizer) -> ()){
            block(tap)
        }
    }
    
    public func removeAllSubviews()
    {
        while (self.subviews.count > 0) {
            let child = self.subviews.last!
            child.removeFromSuperview()
        }
    }
    
    @objc public var size:CGSize{
        get{
            return frame.size
        }
        set{
            var temp=frame
            temp.size=newValue
            frame=temp
        }
    }
    
    @objc public var centerX:CGFloat{
        get{
            return center.x
        }
        set{
            center.x=newValue
        }
    }
    
    @objc public var centerY:CGFloat{
        get{
            return center.y
        }
        set{
            center.y=newValue
        }
    }
    
    @objc public var x:CGFloat{
        get{
            return frame.origin.x
        }
        set{
            var temp = frame
            temp.origin.x = newValue
            frame = temp
        }
    }
    
    @objc public var y:CGFloat{
        get{
            return frame.origin.y
        }
        set{
            var temp = frame
            temp.origin.y = newValue
            frame = temp
        }
    }
    
    @objc public var top:CGFloat{
        get{
            return frame.origin.y
        }
        set{
            var temp = frame
            temp.origin.y = newValue
            frame = temp
        }
    }
    
//    @objc public var bottom:CGFloat{
//        get{
//            return frame.origin.y+frame.size.height
//        }
//        set{
//            var temp = frame
//            temp.origin.y = newValue-frame.size.height
//            frame = temp
//        }
//    }
    
    @objc public var left:CGFloat{
        get{
            return frame.origin.x
        }
        set{
            var temp = frame
            temp.origin.x = newValue
            frame = temp
        }
    }
    
    @objc public var right:CGFloat{
        get{
            return frame.origin.x+frame.size.width
        }
        set{
            var temp = frame
            temp.size.width = newValue-temp.origin.x
            frame = temp
        }
    }
    
//    @objc public var width:CGFloat{
//        get{
//            return frame.size.width
//        }
//        set{
//            var temp = frame
//            temp.size.width = newValue
//            frame = temp
//        }
//    }
    public var height:CGFloat{
        get{
            return frame.size.height
        }
        set{
            var temp = frame
            temp.size.height = newValue
            frame = temp
        }
    }
}


extension UIImage
{
    dynamic public class func imageWithColor(_ color:UIColor,width:CGFloat=1,height:CGFloat=1)->UIImage{
        // 描述矩形
        let rect = CGRect(x:0,y:0,width:width,height:height)
        // 开启位图上下文
        UIGraphicsBeginImageContext(rect.size)
        // 获取位图上下文
        let context = UIGraphicsGetCurrentContext()
        // 使用color演示填充上下文
        context?.setFillColor(color.cgColor)
        // 渲染上下文
        context?.fill(rect)
        // 从上下文中获取图片
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        // 结束上下文
        UIGraphicsEndImageContext()
        return image
    }
}

extension Data
{
    public init(hex: String) {
        self.init(bytes: Array<UInt8>(hex: hex))
    }
    public var bytes: Array<UInt8> {
        return Array(self)
    }
    public func toHexString() -> String {
        return bytes.toHexString()
    }
}

extension Array where Element:NSCopying
{
    public init(reserveCapacity: Int) {
        self = Array<Element>()
        self.reserveCapacity(reserveCapacity)
    }
    
    var slice: ArraySlice<Element> {
        return self[self.startIndex ..< self.endIndex]
    }
    ///返回元素支持拷贝数组的深拷贝
    public var copy:[Element]{
        return self.map {$0.copy(with: nil) as! Element}
    }
}

extension Array
{
    public init(reserveCapacity: Int) {
        self = Array<Element>()
        self.reserveCapacity(reserveCapacity)
    }
    
    var slice: ArraySlice<Element> {
        return self[self.startIndex ..< self.endIndex]
    }
}

extension Array where Element == UInt8
{
    public init(hex: String) {
        self.init(reserveCapacity: hex.unicodeScalars.lazy.underestimatedCount)
        var buffer: UInt8?
        var skip = hex.hasPrefix("0x") ? 2 : 0
        for char in hex.unicodeScalars.lazy {
            guard skip == 0 else {
                skip -= 1
                continue
            }
            guard char.value >= 48 && char.value <= 102 else {
                removeAll()
                return
            }
            let v: UInt8
            let c: UInt8 = UInt8(char.value)
            switch c {
            case let c where c <= 57:
                v = c - 48
            case let c where c >= 65 && c <= 70:
                v = c - 55
            case let c where c >= 97:
                v = c - 87
            default:
                removeAll()
                return
            }
            if let b = buffer {
                append(b << 4 | v)
                buffer = nil
            } else {
                buffer = v
            }
        }
        if let b = buffer {
            append(b)
        }
    }
    
    public func toHexString() -> String {
        return `lazy`.reduce("") {
            var s = String($1, radix: 16)
            if s.count == 1 {
                s = "0" + s
            }
            return $0 + s
        }
    }
}

struct ImageConst{
    static let bytesPerPixel = 4
    static let bitsPerComponent = 8
}

extension UIImage
{
    func s_decodedImage() -> UIImage?{
        guard let cgImage = self.cgImage else{
            return nil
        }
        guard let colorspace = cgImage.colorSpace else {
            return nil
        }
        let alpha = cgImage.alphaInfo
        let anyAlpha = (alpha == .first ||
            alpha == .last ||
            alpha == .premultipliedFirst ||
            alpha == .premultipliedLast)
        // do not decode images with alpha
        if anyAlpha {
            return self;
        }
        let width = cgImage.width
        let height = cgImage.height
        let bytesPerRow = ImageConst.bytesPerPixel * width
        let ctx = CGContext(data: nil,
                            width: width,
                            height: height,
                            bitsPerComponent: ImageConst.bitsPerComponent,
                            bytesPerRow: bytesPerRow,
                            space: colorspace,
                            bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue)
        guard let context = ctx else {
            return nil
        }
        let rect = CGRect(x: 0, y: 0, width: width, height: height)
        context.draw(cgImage, in: rect)
        guard let drawedImage = context.makeImage() else{
            return nil
        }
        let result = UIImage(cgImage: drawedImage, scale:self.scale , orientation: self.imageOrientation)
        return result
    }
}

extension UIButton{
    @objc func asyncSetImage(_ image:UIImage?, for state:UIControl.State){
        DispatchQueue.global(qos: .userInteractive).async {
            let decodeImage = image?.s_decodedImage()
            DispatchQueue.safeMainAsync {
                self.setImage(decodeImage, for: state)
            }
        }
    }
}
